#ifndef _DD_BUFFERBLOCK_H_
#define _DD_BUFFERBLOCK_H_

#include "stdio.h"
#include "memory.h"
#include "malloc.h"

#define DKQ_ALIGNED_MALLOC 

typedef struct _tagDDBufferBlock
{
	unsigned char *pBuffer;
	unsigned long lLength;
	unsigned long lCapacity;

	_tagDDBufferBlock()
	{
		memset(this,0,sizeof(*this));
	}

	~_tagDDBufferBlock()
	{
		Release();
	}

	void Release()
	{
		if( NULL != pBuffer )
		{
#ifdef DKQ_ALIGNED_MALLOC
			_aligned_free(pBuffer);
#else
			delete[]pBuffer;
#endif
			pBuffer = NULL;
		}
		lLength   = 0;
		lCapacity = 0;
	}

	bool Allocate(unsigned long lNewSize)
	{
		if( lNewSize > lCapacity )
		{
			if( NULL != pBuffer )
			{
#ifdef DKQ_ALIGNED_MALLOC
				_aligned_free(pBuffer);
#else
				delete[]pBuffer;
#endif
				pBuffer = NULL;
			}

			lNewSize += 100;
#ifdef DKQ_ALIGNED_MALLOC
			pBuffer = (unsigned char *)_aligned_malloc(lNewSize, 16);
#else
			pBuffer = new unsigned char[lNewSize];
#endif		
			if( NULL == pBuffer )
			{
				return false;
			}

			lCapacity = lNewSize;
			
			memset(pBuffer,0,lCapacity);
		}

		lLength = 0;
		if( NULL != pBuffer )
		{
			return true;
		}

		return false;
	}

	bool Enlarge(unsigned long lNewSize)
	{
		if( lNewSize > lCapacity )
		{
			lNewSize += 100;
#ifdef DKQ_ALIGNED_MALLOC
			unsigned char *pNewBuffer = (unsigned char *)_aligned_malloc(lNewSize, 16);
#else
			unsigned char *pNewBuffer = new unsigned char[lNewSize];
#endif		
			if( NULL == pNewBuffer )
			{
				return false;
			}
			memset(pNewBuffer,0,lNewSize);

			if( NULL != pBuffer )
			{
				if( lLength > 0 )
				{
					memcpy(pNewBuffer,pBuffer,lLength);
				}
#ifdef DKQ_ALIGNED_MALLOC
				_aligned_free(pBuffer);
#else
				delete[]pBuffer;
#endif
			}

			lCapacity = lNewSize;
			pBuffer   = pNewBuffer;
		}

		if( NULL != pBuffer )
		{
			return true;
		}

		return false;
	}

	bool Resize(long lSize)
	{
		if( NULL != pBuffer )
		{
#ifdef DKQ_ALIGNED_MALLOC
			_aligned_free(pBuffer);
#else
			delete[]pBuffer;
#endif
			pBuffer = NULL;
		}
		lLength   = 0;
		lCapacity = 0;

		lSize += 100;

#ifdef DKQ_ALIGNED_MALLOC
		pBuffer = (unsigned char *)_aligned_malloc(lSize, 16);
#else
		pBuffer = new unsigned char[lSize];
#endif	
		if( NULL == pBuffer )
		{
			return false;
		}
		lCapacity = lSize;
		memset(pBuffer,0,lSize);

		return true;
	}

	void MemSet()
	{
		if( NULL != pBuffer )
		{
			memset(pBuffer,0,lCapacity);
		}
	}

}DDBufferBlock;

typedef struct _tagDDBufferBlock2
{
	unsigned char *pBuffer;
	unsigned long lCapacity;
	
	unsigned char *pCache1;
	unsigned char *pCache2;
	BOOL           bCache1Idle;
	

	_tagDDBufferBlock2()
	{
		memset(this,0,sizeof(*this));
	}

	~_tagDDBufferBlock2()
	{
		Release();
	}

	void Release()
	{
		pBuffer = NULL;

		if( NULL != pCache1 )
		{
#ifdef DKQ_ALIGNED_MALLOC
			_aligned_free(pCache1);
#else
			delete[]pCache1;
#endif
			pCache1 = NULL;
		}
		if( NULL != pCache2 )
		{
#ifdef DKQ_ALIGNED_MALLOC
			_aligned_free(pCache2);
#else
			delete[]pCache2;
#endif
			pCache2 = NULL;
		}
		lCapacity = 0;
	}

	bool Allocate(unsigned long lNewSize)
	{
		if( lNewSize > lCapacity )
		{
			pBuffer     = NULL;
			bCache1Idle = FALSE;

			lNewSize += 100;
			
#ifdef DKQ_ALIGNED_MALLOC
			pCache1 = (unsigned char *)_aligned_malloc(lNewSize, 16);
#else
			pCache1 = new unsigned char[lNewSize];
#endif
			if( NULL == pCache1 )
			{
				return false;
			}

#ifdef DKQ_ALIGNED_MALLOC
			pCache2 = (unsigned char *)_aligned_malloc(lNewSize, 16);
#else
			pCache2 = new unsigned char[lNewSize];
#endif
			if( NULL == pCache2 )
			{
				return false;
			}

			lCapacity = lNewSize;

			memset(pCache1,0,lNewSize);
			memset(pCache2,0,lNewSize);

			GetIdleBuffer();
		}


		if( NULL != pCache1 && NULL != pCache2 )
		{
			return true;
		}

		return false;
	}

	unsigned char * GetIdleBuffer()
	{
		pBuffer = bCache1Idle?pCache1:pCache2;
		bCache1Idle = !bCache1Idle;

		return pBuffer;
	}

	void MemSet()
	{
		if( NULL != pCache1 )
		{
			memset(pCache1,0,lCapacity);
		}
		if( NULL != pCache2 )
		{
			memset(pCache2,0,lCapacity);
		}
	}

}DDBufferBlock2;

#endif